package com.zf.multilang.security;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;

//@Component . XssFilter.java（移除 @Component 注解，改为构造函数注入）
public class XssFilter implements Filter {

    private static final Logger log = LoggerFactory.getLogger(XssFilter.class);

    private final ObjectMapper objectMapper;//实例变量，一次赋值机会
    // 通过构造函数注入依赖
    public XssFilter(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;

        try {
            // 仅处理 POST/PUT 等有请求体的请求
            if (isJsonRequest(req)) {
                XssRequestWrapper wrapper = new XssRequestWrapper(req);
                String body = StreamUtils.copyToString(wrapper.getInputStream(), StandardCharsets.UTF_8);
                if (body.isEmpty()) {
                    chain.doFilter(wrapper, resp);
                    return;
                }

                // 解析 JSON
                Map<String, Object> jsonMap;
                try {
                    jsonMap = objectMapper.readValue(body, Map.class);
                } catch (JsonProcessingException e) {
                    // 非法 JSON，直接拒绝
                    resp.setStatus(400);
                    resp.getWriter().write("{\"error\":\"Invalid JSON\"}");
                    return;
                }

                // 清理 XSS
                Map<String, Object> cleanedMap = XssUtils.cleanMap(jsonMap);
                // 重新序列化
                String cleanedJson = objectMapper.writeValueAsString(cleanedMap);
                CachedBodyHttpServletRequest wrappedRequest = new CachedBodyHttpServletRequest(req, cleanedJson.getBytes(StandardCharsets.UTF_8));
                chain.doFilter(wrappedRequest, resp);

            } else {
                // 表单请求，直接包装
                XssRequestWrapper wrapper = new XssRequestWrapper(req);
                chain.doFilter(wrapper, resp);
            }

        } catch (Exception e) {
            log.error("XSS Filter error", e);
            resp.setStatus(500);
            resp.getWriter().write("{\"error\":\"Server Error\"}");
        }
    }

    private boolean isJsonRequest(HttpServletRequest request) {
        String contentType = request.getContentType();
        return contentType != null &&
               contentType.toLowerCase().contains(MediaType.APPLICATION_JSON_VALUE);
    }
}
/*

        为什么移除 @Component？
        @Component 会自动注册 XssFilter 为 Spring Bean。
        如果同时通过 FilterRegistrationBean 注册同名 Bean，会导致冲突。
        显式注册更可控，避免 Spring 自动注册的不确定性。
        为什么用构造函数注入？
        XssFilter 是普通类（非 Spring Bean），无法通过 @Autowired 注入依赖。
        通过构造函数传入 ObjectMapper，确保依赖注入正确。
        如何保证依赖可用？
        在 SecurityFilterConfig 中注入 ObjectMapper（Spring 提供的 Bean）。
        将其传递给 XssFilter 的构造函数，完成依赖注入。


*/
